package managedbean.stakeholder;

import entity.AddressEntity;
import entity.OperatingHoursEntity;
import entity.CuisineTypeEntity;
import entity.ExtendedOperatingHoursEntity;
import entity.FnBBranchEntity;
import entity.OperatingHoursRemarksEntity;
import entity.StakeholderEntity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseEvent;
import session.stateless.BranchSessionBean;
import session.stateless.SystemMessagesBean;
import util.enumeration.CuisineType;
import util.enumeration.OperatingDay;
import util.enumeration.OperatingHours;
import util.enumhelper.OperatingHrs;
import util.localization.WebLocalization;

/**
 *
 * @author Amelia
 */
@ManagedBean
@ViewScoped
public class EditBranchManagedBean implements Serializable {
    //Exception

    @EJB
    private SystemMessagesBean systemMessages;
    //User Selected Locale
    private String preferredLocale;
    private String previousLocale = "";
    private WebLocalization localization;
    @EJB
    private BranchSessionBean branchSessionBean;
    private StakeholderEntity stakeholder;
    private AddressEntity branchAddressToEdit;
    private FnBBranchEntity fnbBranchToEdit;
    private OperatingHoursRemarksEntity operatingHoursRemarksToEdit;
    private List<CuisineTypeEntity> cuisinePrefToEdit;
    private List<OperatingHrs> extendedOperatingHoursList;
    private List<OperatingHoursEntity> branchOperatingHoursToEdit;
    List<ExtendedOperatingHoursEntity> extOpHrsList;
    private List<CuisineType> cuisineTypeList;
    private List<OperatingHrs> operatingHrsList;
    private OperatingDay[] operatingDay = OperatingDay.values();
    private OperatingDay normalOperatingDay;
    private OperatingHours openingHours;
    private OperatingHours closingHours;
    private OperatingHours extendedTimeStart;
    private OperatingHours extendedTimeEnd;
    private Date extendedCalendarDate;
    private boolean branchEdited;

    /** Creates a new instance of EditBranchManagedBean */
    public EditBranchManagedBean() {
    }

    /************************************************************************************\
    /******************************** GET SET METHODS ***********************************\
    /************************************************************************************/
    public AddressEntity getBranchAddressToEdit() {
        return branchAddressToEdit;
    }

    public void setBranchAddressToEdit(AddressEntity branchAddressToEdit) {
        this.branchAddressToEdit = branchAddressToEdit;
    }

    public FnBBranchEntity getFnbBranchToEdit() {
        return fnbBranchToEdit;
    }

    public void setFnbBranchToEdit(FnBBranchEntity fnbBranchToEdit) {
        this.fnbBranchToEdit = fnbBranchToEdit;
    }

    public OperatingHoursRemarksEntity getOperatingHoursRemarksToEdit() {
        return operatingHoursRemarksToEdit;
    }

    public void setOperatingHoursRemarksToEdit(OperatingHoursRemarksEntity operatingHoursRemarksToEdit) {
        this.operatingHoursRemarksToEdit = operatingHoursRemarksToEdit;
    }

    public List<CuisineTypeEntity> getCuisinePrefToEdit() {
        return cuisinePrefToEdit;
    }

    public void setCuisinePrefToEdit(List<CuisineTypeEntity> cuisinePrefToEdit) {
        this.cuisinePrefToEdit = cuisinePrefToEdit;
    }

    public List<OperatingHoursEntity> getBranchOperatingHoursToEdit() {
        return branchOperatingHoursToEdit;
    }

    public void setBranchOperatingHoursToEdit(List<OperatingHoursEntity> branchOperatingHoursToEdit) {
        this.branchOperatingHoursToEdit = branchOperatingHoursToEdit;
    }

    public List<OperatingHrs> getExtendedOperatingHoursList() {
        return extendedOperatingHoursList;
    }

    public void setExtendedOperatingHoursList(List<OperatingHrs> extendedOperatingHoursList) {
        this.extendedOperatingHoursList = extendedOperatingHoursList;
    }

    public List<CuisineType> getCuisineTypeList() {
        return cuisineTypeList;
    }

    public void setCuisineTypeList(List<CuisineType> cuisineTypeList) {
        this.cuisineTypeList = cuisineTypeList;
    }

    public List<OperatingHrs> getOperatingHrsList() {
        return operatingHrsList;
    }

    public void setOperatingHrsList(List<OperatingHrs> operatingHrsList) {
        this.operatingHrsList = operatingHrsList;
    }

    public OperatingHours getExtendedTimeStart() {
        return extendedTimeStart;
    }

    public void setExtendedTimeStart(OperatingHours extendedTimeStart) {
        this.extendedTimeStart = extendedTimeStart;
    }

    public OperatingHours getExtendedTimeEnd() {
        return extendedTimeEnd;
    }

    public void setExtendedTimeEnd(OperatingHours extendedTimeEnd) {
        this.extendedTimeEnd = extendedTimeEnd;
    }

    public Date getExtendedCalendarDate() {
        return extendedCalendarDate;
    }

    public void setExtendedCalendarDate(Date extendedCalendarDate) {
        this.extendedCalendarDate = extendedCalendarDate;
    }

    public OperatingDay[] getOperatingDay() {
        return operatingDay;
    }

    public void setOperatingDay(OperatingDay[] operatingDay) {
        this.operatingDay = operatingDay;
    }

    public OperatingDay getNormalOperatingDay() {
        return normalOperatingDay;
    }

    public void setNormalOperatingDay(OperatingDay normalOperatingDay) {
        this.normalOperatingDay = normalOperatingDay;
    }

    public OperatingHours getOpeningHours() {
        return openingHours;
    }

    public void setOpeningHours(OperatingHours openingHours) {
        this.openingHours = openingHours;
    }

    public OperatingHours getClosingHours() {
        return closingHours;
    }

    public void setClosingHours(OperatingHours closingHours) {
        this.closingHours = closingHours;
    }

    /************************************************************************************\
    /*********************************** METHODS ****************************************\
    /************************************************************************************/
    public void initView(PhaseEvent event) {
        /* LOCALIZATION */
        localization = new WebLocalization();
        preferredLocale = localization.getPreferredLocaleFromSession();
        /* END LOCALIZATION */
        FacesContext.getCurrentInstance().getExternalContext().getFlash().clear();
        FacesContext.getCurrentInstance().getExternalContext().getSession(true);
        /*
        if (stakeholder == null) {
        stakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholderEntity");
        }
        if (branchToEdit == null) {
        branchToEdit = (FnbBranchState) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("selectedBranch");
        }*/

        if (fnbBranchToEdit == null) {
            fnbBranchToEdit = (FnBBranchEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("selectedFnBBranch");
        }
        if (branchAddressToEdit == null) {
            branchAddressToEdit = branchSessionBean.viewBranchAddress(fnbBranchToEdit.getId());
        }

        if (cuisinePrefToEdit == null) {
            this.cuisineTypeList = new ArrayList<CuisineType>();
            cuisinePrefToEdit = branchSessionBean.viewCuisinePref(fnbBranchToEdit.getId());
            //Database records will be placed into the cuisineType enum arraylist which is mapped onto editBranch.xhtml
            for (int i = 0; i < getCuisinePrefToEdit().size(); i++) {
                //arraylist add the values
                cuisineTypeList.add(getCuisinePrefToEdit().get(i).getCuisineType());
            }
        }

        if (branchOperatingHoursToEdit == null) {
            this.operatingHrsList = new ArrayList<OperatingHrs>();
            branchOperatingHoursToEdit = branchSessionBean.viewBranchOperatingHours(fnbBranchToEdit.getId());
            for (int i = 0; i < branchOperatingHoursToEdit.size(); i++) {
                OperatingHrs opHrClass = new OperatingHrs(branchOperatingHoursToEdit.get(i).getOperatingDayEnum(), branchOperatingHoursToEdit.get(i).getOperatingDay(), branchOperatingHoursToEdit.get(i).getOpeningHoursEnum(), branchOperatingHoursToEdit.get(i).getOpeningHours(), branchOperatingHoursToEdit.get(i).getClosingHoursEnum(), branchOperatingHoursToEdit.get(i).getClosingHours());
                operatingHrsList.add(opHrClass);
            }
        }

        if (extOpHrsList == null) {
            this.extendedOperatingHoursList = new ArrayList<OperatingHrs>();
            this.extOpHrsList = new ArrayList<ExtendedOperatingHoursEntity>();
            extOpHrsList = branchSessionBean.viewExtendedOperatingHours(fnbBranchToEdit.getId());
            for (int i = 0; i < extOpHrsList.size(); i++) {
                OperatingHrs opHrClass = new OperatingHrs(extOpHrsList.get(i).getOperatingDayEnum(), extOpHrsList.get(i).getOperatingDay(), extOpHrsList.get(i).getOpeningHoursEnum(), extOpHrsList.get(i).getOpeningHours(), extOpHrsList.get(i).getClosingHoursEnum(), extOpHrsList.get(i).getClosingHours(), extOpHrsList.get(i).getSpecificDate());
                extendedOperatingHoursList.add(opHrClass);
            }
        }
        if (operatingHoursRemarksToEdit == null || !previousLocale.equals(preferredLocale)) {
            OperatingHoursRemarksEntity operatingHoursRemarks = branchSessionBean.viewOperatingHoursRemarks(preferredLocale, fnbBranchToEdit.getId());
            operatingHoursRemarksToEdit = operatingHoursRemarks;
        }
        previousLocale = preferredLocale;
    }

    public void editBranch(ActionEvent event) {
        if (checkOperatingDayList() == false) { //if all operating days are being selected
            branchEdited = branchSessionBean.editBranchDetails(getFnbBranchToEdit(),
                    getBranchAddressToEdit(), getFnbBranchToEdit().getBranchName(), getFnbBranchToEdit().getBranchAddress().getPostalCode(),
                    getFnbBranchToEdit().getBranchAddress().getBlkNumber(), getFnbBranchToEdit().getBranchAddress().getStreetName(),
                    getFnbBranchToEdit().getBranchAddress().getUnitNumber(), getFnbBranchToEdit().getBranchAddress().getBuildingName(), getFnbBranchToEdit().getContactNumber(),
                    getFnbBranchToEdit().getContactPerson(), getFnbBranchToEdit().getEmailAddress(), getFnbBranchToEdit().getFnBType(),
                    getFnbBranchToEdit().getIsHalal(), getFnbBranchToEdit().getPriceRange(), preferredLocale, operatingHoursRemarksToEdit.getRemarks(), cuisineTypeList, operatingHrsList, extendedOperatingHoursList);

            if (branchEdited == true) {
                String statusMessage = systemMessages.getSystemMessage("BRANCH_EDIT_SUCCESS", preferredLocale);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, statusMessage));
            } else {
                String statusMessage = systemMessages.getSystemMessage("BRANCH_EDIT_NOT_SUCCESSFUL", preferredLocale);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, statusMessage));
            }
        }
    }

    //Add operating hours
    public void addOperatingHours() {
        OperatingHrs operatingHours = new OperatingHrs();
        boolean duplicate = false;

        if (openingHours.getTime().equals(closingHours.getTime())
                && !(openingHours.getLabel().equals("OFF") && closingHours.getLabel().equals("OFF"))) {
            String statusMessage = systemMessages.getSystemMessage("START_TIME_END_TIME_MUST_BE_DIFFERENT", preferredLocale);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
        } else if ((openingHours.getLabel().equals("OFF") && !(closingHours.getLabel().equals("OFF")))
                || (!(openingHours.getLabel().equals("OFF")) && closingHours.getLabel().equals("OFF"))) {
            String statusMessage = systemMessages.getSystemMessage("START_TIME_END_TIME_MUST_BE_OFF", preferredLocale);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
        } else if (openingHours.getTime().after(closingHours.getTime())) {
            String statusMessage = systemMessages.getSystemMessage("START_TIME_MUST_BE_BEFORE_END_TIME", preferredLocale);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
        } // if all goes well....
        else {
            operatingHours = new OperatingHrs(normalOperatingDay, normalOperatingDay.getLabel(), openingHours, openingHours.getTime(), closingHours, closingHours.getTime());
            //If there is no record exist in the list, add to arraylist
            if (operatingHrsList.isEmpty()) {
                operatingHrsList.add(operatingHours);
                String statusMessage = systemMessages.getSystemMessage("ADDED_TO_LIST", preferredLocale);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, statusMessage));
            } else {
                //traverse array list to search for duplicate record
                //if exists, set msg and break from loop
                for (int i = 0; i < operatingHrsList.size(); i++) {
                    //Check both dates is equal
                    if (operatingHrsList.get(i).getOperatingDayEnum().equals(operatingHours.getOperatingDayEnum())
                            && (((operatingHours.getOpeningHours().after(operatingHrsList.get(i).getOpeningHours()) && operatingHours.getOpeningHours().before(operatingHrsList.get(i).getClosingHours()))
                            || (operatingHours.getClosingHours().after(operatingHrsList.get(i).getOpeningHours()) && operatingHours.getClosingHours().before(operatingHrsList.get(i).getClosingHours())))
                            || (operatingHours.getOpeningHours().equals(operatingHrsList.get(i).getOpeningHours()) && operatingHours.getClosingHours().equals(operatingHrsList.get(i).getClosingHours())))) {
                        //if all true, return duplicate msg
                        String statusMessage = systemMessages.getSystemMessage("DUPLICATE_TIME", preferredLocale);
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
                        duplicate = true;
                        break;
                    }
                }

                //if there's no duplicate records in arraylist, add new record into list
                if (duplicate == false) {
                    for (int i = 0; i < operatingHrsList.size(); i++) {
                        if (i != (operatingHrsList.size() - 1)) { //not the last value in the list
                            if (operatingHours.getOperatingDayEnum().getDay() < operatingHrsList.get(i).getOperatingDayEnum().getDay()) {
                                operatingHrsList.add(i, operatingHours);
                                break;
                            } else if (operatingHours.getOperatingDayEnum().getDay() >= operatingHrsList.get(i).getOperatingDayEnum().getDay()
                                    && operatingHours.getOperatingDayEnum().getDay() < operatingHrsList.get(i + 1).getOperatingDayEnum().getDay()) {
                                if (operatingHours.getClosingHours().before(operatingHrsList.get(i).getOpeningHours()) || operatingHours.getClosingHours().equals(operatingHrsList.get(i).getOpeningHours())) {
                                    operatingHrsList.add(i, operatingHours);
                                } else {
                                    operatingHrsList.add(i + 1, operatingHours);
                                }
                                break;
                            }
                        } else if (operatingHours.getOperatingDayEnum().getDay() >= operatingHrsList.get(i).getOperatingDayEnum().getDay()
                                && ((operatingHrsList.size() - 1) == i)) {
                            if (operatingHours.getClosingHours().before(operatingHrsList.get(i).getOpeningHours()) || operatingHours.getClosingHours().equals(operatingHrsList.get(i).getOpeningHours())) {
                                operatingHrsList.add(i, operatingHours);
                            } else {
                                operatingHrsList.add(i + 1, operatingHours);
                            }
                            break;
                        } else if (operatingHrsList.size() == 1) { //if 1 record exist, check the date and add according to the day
                            if (operatingHours.getOperatingDayEnum().getDay() < operatingHrsList.get(0).getOperatingDayEnum().getDay()) {
                                operatingHrsList.add(0, operatingHours);
                                break;
                            } else if (operatingHours.getOperatingDayEnum().getDay() > operatingHrsList.get(0).getOperatingDayEnum().getDay()) {
                                operatingHrsList.add(operatingHours);
                                break;
                            } else {
                                if (operatingHours.getClosingHours().before(operatingHrsList.get(i).getOpeningHours()) || operatingHours.getClosingHours().equals(operatingHrsList.get(i).getOpeningHours())) {
                                    operatingHrsList.add(0, operatingHours);
                                } else {
                                    operatingHrsList.add(operatingHours);
                                }
                                break;
                            }
                        } else {
                            operatingHrsList.add(operatingHours);
                            break;
                        }
                    }
                    String statusMessage = systemMessages.getSystemMessage("ADDED_TO_LIST", preferredLocale);
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, statusMessage));
                }
            }
        }
    }

    /*Remove a particular operating day from the datatable*/
    public void removeOperatingHoursList(OperatingHrs operatingHours) {
        operatingHrsList.remove(operatingHours);
        String statusMessage = systemMessages.getSystemMessage("REMOVED_FROM_LIST", preferredLocale);
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, statusMessage));
    }

    public boolean checkOperatingDayList() {
        List<OperatingDay> listOfMissingDays = new ArrayList<OperatingDay>();
        if (!operatingHrsList.isEmpty()) {
            listOfMissingDays.add(operatingHrsList.get(0).getOperatingDayEnum());
            for (int i = 0; i < operatingHrsList.size(); i++) {
                if (!listOfMissingDays.contains(operatingHrsList.get(i).getOperatingDayEnum())) {
                    listOfMissingDays.add(operatingHrsList.get(i).getOperatingDayEnum()); //add all the non duplicated day into missing day list
                }
            }
            if (listOfMissingDays.size() < 7) { //if there is any missing days
                String monday, tuesday, wednesday, thursday, friday, sat, sun;
                String statusMessage = systemMessages.getSystemMessage("BRANCH_OPERATING_DAYS", preferredLocale);
                if (!listOfMissingDays.contains(OperatingDay.MONDAY)) {
                    //listOfMissingDays.remove(OperatingDay.MONDAY); //remove MONDAY from list if exist
                    monday = systemMessages.getSystemMessage("BRANCH_OPERATINGDAYS_MONDAY", preferredLocale);
                    statusMessage += monday + " ";
                }
                if (!listOfMissingDays.contains(OperatingDay.TUESDAY)) {
                    //listOfMissingDays.remove(OperatingDay.TUESDAY); //remove TUESDAY from list if exist
                    tuesday = systemMessages.getSystemMessage("BRANCH_OPERATINGDAYS_TUESDAY", preferredLocale);
                    statusMessage += tuesday + " ";
                }
                if (!listOfMissingDays.contains(OperatingDay.WEDNESDAY)) {
                    //listOfMissingDays.remove(OperatingDay.WEDNESDAY); //remove WEDNESDAY from list if exist
                    wednesday = systemMessages.getSystemMessage("BRANCH_OPERATINGDAYS_WEDNESDAY", preferredLocale);
                    statusMessage += wednesday + " ";
                }
                if (!listOfMissingDays.contains(OperatingDay.THURSDAY)) {
                    //listOfMissingDays.remove(OperatingDay.THURSDAY); //remove THURSDAY from list if exist
                    thursday = systemMessages.getSystemMessage("BRANCH_OPERATINGDAYS_THURSDAY", preferredLocale);
                    statusMessage += thursday + " ";
                }
                if (!listOfMissingDays.contains(OperatingDay.FRIDAY)) {
                    //listOfMissingDays.remove(OperatingDay.FRIDAY); //remove FRIDAY from list if exist
                    friday = systemMessages.getSystemMessage("BRANCH_OPERATINGDAYS_FRIDAY", preferredLocale);
                    statusMessage += friday + " ";
                }
                if (!listOfMissingDays.contains(OperatingDay.SATURDAY)) {
                    //listOfMissingDays.remove(OperatingDay.SATURDAY); //remove SATURDAY from list if exist
                    sat = systemMessages.getSystemMessage("BRANCH_OPERATINGDAYS_SATURDAY", preferredLocale);
                    statusMessage += sat + " ";
                }
                if (!listOfMissingDays.contains(OperatingDay.SUNDAY)) {
                    //listOfMissingDays.remove(OperatingDay.SUNDAY); //remove SUNDAY from list if exist
                    sun = systemMessages.getSystemMessage("BRANCH_OPERATINGDAYS_SUNDAY", preferredLocale);
                    statusMessage += sun + " ";
                }

                statusMessage += systemMessages.getSystemMessage("IS_NOT_SELECTED", preferredLocale);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
                return true;
            }
        } else {
            String statusMessage = systemMessages.getSystemMessage("OPERATING_HOURS_ARE_SELECTED", preferredLocale);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
            return true;
        }
        return false; //if all 7 days are included in the list, clear the list and return it empty to indicate no missing days
    }

    //Add a specific date list for extended operating hours
    public void addSpecificDateList() {
        OperatingHrs specificOperatingHrs = new OperatingHrs();
        boolean duplicate = false;

        //Check calendar date is empty or not
        if (extendedCalendarDate != null) {
            Date todayDate = new Date();
            //entered calendar date has to be after today's date
            if (extendedCalendarDate.before(todayDate) && !(extendedCalendarDate.equals(todayDate))) {
                String statusMessage = systemMessages.getSystemMessage("EXTENDED_DATE_NOT_BEFORE_TODAY'S_DATE", preferredLocale);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
            } else {
                //check whether the time entered is equal except for off
                if (extendedTimeStart.getTime().equals(extendedTimeEnd.getTime())
                        && !(extendedTimeStart.getLabel().equals("OFF") && extendedTimeEnd.getLabel().equals("OFF"))) {
                    String statusMessage = systemMessages.getSystemMessage("EXTENDED_START_TIME_END_TIME_MUST_BE_DIFFERENT", preferredLocale);
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
                } /*else if (extendedTimeStart.getTime().after(extendedTimeEnd.getTime())
                && (!(extendedTimeStart.getLabel().equals("OFF") && !(extendedTimeEnd.getLabel().equals("OFF"))))) {
                //String statusMessage = systemMessages.getSystemMessage("CREATION_SUCCESS", selectedLocale);
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Extended Operating Hours: Select an appropriate time range", "Extended Operating Hours: Select an appropriate time range"));
                } */ //check if 1 time is entered off, the other must also be off
                else if ((extendedTimeStart.getLabel().equals("OFF") && !(extendedTimeEnd.getLabel().equals("OFF")))
                        || (!(extendedTimeStart.getLabel().equals("OFF")) && extendedTimeEnd.getLabel().equals("OFF"))) {
                    String statusMessage = systemMessages.getSystemMessage("EXTENDED_START_TIME_END_TIME_MUST_BE_OFF", preferredLocale);
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
                } // if all goes well....
                else {
                    //Select the day string value from enum(Compare calendar day(int value) to enum day(int value))
                    for (int i = 0; i < getOperatingDay().length; i++) {
                        if (extendedCalendarDate.getDay() == getOperatingDay()[i].getDay()) {
                            String day = getOperatingDay()[i].getLabel();
                            specificOperatingHrs = new OperatingHrs(getOperatingDay()[i], day, extendedTimeStart, extendedTimeStart.getTime(), extendedTimeEnd, extendedTimeEnd.getTime(), extendedCalendarDate);
                        }
                    }
                    //If there is no record exist in the list, add to arraylist
                    if (extendedOperatingHoursList.isEmpty()) {
                        extendedOperatingHoursList.add(specificOperatingHrs);
                        String statusMessage = systemMessages.getSystemMessage("ADDED_TO_LIST", preferredLocale);
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, statusMessage));
                    } else {
                        //traverse array list to search for duplicate record
                        //if exists, set msg and break from loop
                        for (int i = 0; i < extendedOperatingHoursList.size(); i++) {
                            //Check both dates is equal
                            if (extendedOperatingHoursList.get(i).getSpecificDate().equals(specificOperatingHrs.getSpecificDate())
                                    && ( //check new opening time has to be after closing time
                                    (extendedOperatingHoursList.get(i).getClosingHours().after(specificOperatingHrs.getOpeningHours()))
                                    || //check both opening n closing is equal
                                    (extendedOperatingHoursList.get(i).getOpeningHours().equals(specificOperatingHrs.getOpeningHours())
                                    && extendedOperatingHoursList.get(i).getClosingHours().equals(specificOperatingHrs.getClosingHours())))) {
                                //if all true, return duplicate msg
                                String statusMessage = systemMessages.getSystemMessage("DUPLICATE_DATE", preferredLocale);
                                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
                                duplicate = true;
                                break;
                            }
                        }
                        //if there's no duplicate records in arraylist, add new record into list
                        if (duplicate == false) {
                            extendedOperatingHoursList.add(specificOperatingHrs);
                            String statusMessage = systemMessages.getSystemMessage("ADDED_TO_LIST", preferredLocale);
                            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, statusMessage));
                        }
                    }
                }
            }
        } else {
            String statusMessage = systemMessages.getSystemMessage("EXTENDED_IS_NOT_SELECTED", preferredLocale);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage));
        }
    }

    public void removeSpecificDateList(OperatingHrs extendedOperatingHrs) {
        extendedOperatingHoursList.remove(extendedOperatingHrs);
        String statusMessage = systemMessages.getSystemMessage("REMOVED_FROM_LIST", preferredLocale);
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, statusMessage));
    }

    /************************************************************************************|
    |*********************************** VALIDATION METHODS *****************************|
    |************************************************************************************/
    public void validateOperatingHours(FacesContext context, UIComponent component, Object value) {
        //Get the specific component ID
        String ID = component.getId();
        //Get the end time of the operating hours
        OperatingHours endTime = (OperatingHours) value;
        //Check the component ID
        if (ID.contains("Monday")) {
            String msg = validateOpHrs(component, endTime);
            //if message is not empty, display.
            if (!msg.isEmpty()) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
                context.addMessage(component.getClientId(context), message);
            }
        } else if (ID.contains("Tuesday")) {
            String msg = validateOpHrs(component, endTime);
            //if message is not empty, display.
            if (!msg.isEmpty()) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
                context.addMessage(component.getClientId(context), message);
            }
        } else if (ID.contains("Wednesday")) {
            String msg = validateOpHrs(component, endTime);
            //if message is not empty, display.
            if (!msg.isEmpty()) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
                context.addMessage(component.getClientId(context), message);
            }
        } else if (ID.contains("Thursday")) {
            String msg = validateOpHrs(component, endTime);
            //if message is not empty, display.
            if (!msg.isEmpty()) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
                context.addMessage(component.getClientId(context), message);
            }
        } else if (ID.contains("Friday")) {
            String msg = validateOpHrs(component, endTime);
            //if message is not empty, display.
            if (!msg.isEmpty()) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
                context.addMessage(component.getClientId(context), message);
            }
        } else if (ID.contains("Saturday")) {
            String msg = validateOpHrs(component, endTime);
            //if message is not empty, display.
            if (!msg.isEmpty()) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
                context.addMessage(component.getClientId(context), message);
            }
        } else if (ID.contains("Sunday")) {
            String msg = validateOpHrs(component, endTime);
            //if message is not empty, display.
            if (!msg.isEmpty()) {
                FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
                context.addMessage(component.getClientId(context), message);
            }
        }
    }

    public String validateOpHrs(UIComponent component, OperatingHours endTime) {
        UIInput day = (UIInput) component.getAttributes().get("day");
        OperatingHours startTime = (OperatingHours) day.getValue();

        //If either start time of end time is off
        if (startTime.getLabel().equals("OFF") || endTime.getLabel().equals("OFF")) {
            //if confirm both is off
            if (startTime.getLabel().equals("OFF") && endTime.getLabel().equals("OFF")) {
                return "";
            } else {
                //set the component that value is deemed incorrect to false to disallow submitting of page
                ((UIInput) component).setValid(false);
                //return error message
                String statusMessage = systemMessages.getSystemMessage("OPERATING_HOURS_START_TIME_END_TIME_MUST_BE_OFF", preferredLocale);
                return statusMessage;
            }
        } else if (startTime.getTime().equals(endTime.getTime())) {
            //set the component that value is deemed incorrect to false to disallow submitting of page
            ((UIInput) component).setValid(false);
            //return error message
            String statusMessage = systemMessages.getSystemMessage("OPERATING_HOURS_START_TIME_END_TIME_MUST_BE_DIFFERENT", preferredLocale);
            return statusMessage;
        }
        return "";
    }

    public void validateEmail(FacesContext context, UIComponent toValidate, Object value) {
        String email = (String) value;
        Pattern p = Pattern.compile("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$");

        //Match the given string with the pattern
        Matcher m = p.matcher(email);

        //Check whether match is found
        boolean matchFound = m.matches();

        //if mail does not match the pattern
        if (!matchFound) {
            ((UIInput) toValidate).setValid(false);
            String statusMessage = systemMessages.getSystemMessage("INVALID_EMAIL_ADDRESS", preferredLocale);
            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, statusMessage);
            context.addMessage(toValidate.getClientId(context), message);
        }
    }
}
